package com.chen.webservice.model;

import cn.hutool.core.collection.CollectionUtil;
import com.chen.ga.Chromosome;
import lombok.Data;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * @description: 排片 bean
 * @params:
 * @return:
 * @author: chenzhiwen
 * @dateTime: 2021/10/21 下午7:14
 */
@Data
public class MyOrder implements Chromosome<MyOrder>, Cloneable {

    private static final Random random = new Random();

    private Integer startTime;
    private Integer endTime;

    private List<Order> orders;

    private List<ConfigureParameterDTO.FixOrder> fixOrders;

    private List<Order> oriOrders = new ArrayList<>();  // 原创广告
    private List<Order> covOrders = new ArrayList<>();  // 包屏广告

    public MyOrder() {
        orders = new ArrayList<>();
    }

    public MyOrder(Integer startTime, Integer endTime, List<Order> orders, List<ConfigureParameterDTO.FixOrder> fixOrders) {
        this.startTime = startTime;
        this.endTime = endTime;
        this.orders = orders;
        this.fixOrders = fixOrders;
    }

    public MyOrder(Integer startTime, Integer endTime, List<Order> orders) {
        this.startTime = startTime;
        this.endTime = endTime;
        this.orders = orders;
    }

    /**
     * @description: 变异
     *
     * @params: []
     * @return: com.chen.webservice.Demo2.MyOrder
     * @author: chenzhiwen
     * @dateTime: 2021/10/21 下午7:15
     */
    @Override
    public MyOrder mutate() {
        return mut(5);
    }

    /**
     * 随机变异
     *
     * @param times
     * @return
     */
    private MyOrder mut(int times) {
        MyOrder result = this.clone();
        for (int i = 0; i < times; i++) {

            int count = random.nextInt(10) + 1;

            // just select random element of vector
            // and increase or decrease it on small value
            int index1 = random.nextInt(this.orders.size());
            int index2 = random.nextInt(this.orders.size());
            Order order1 = result.orders.get(index1);
            Order order2 = result.orders.get(index2);
            result.orders.remove(index1);
            result.orders.add(index1, order2);
            result.orders.remove(index2);
            result.orders.add(index2, order1);
            if (random.nextInt(100) <= 0) {
                checkCover(result.orders, result.covOrders, result.oriOrders);
            }
        }

        return result;
    }

    public void zhidinMut(List<Order> orders) {
        int index1 = random.nextInt(orders.size());
        int index2 = random.nextInt(orders.size());
        Order order1 = orders.get(index1);
        Order order2 = orders.get(index2);
        orders.remove(index1);
        orders.add(index1, order2);
        orders.remove(index2);
        orders.add(index2, order1);
    }

    /**
     * @description: 交叉
     * @params: [other]
     * @return: java.util.List<com.chen.webservice.Demo2.MyOrder>
     * @author: chenzhiwen
     * @dateTime: 2021/10/21 下午7:15
     */
    @Override
    public List<MyOrder> crossover(MyOrder other) {
        MyOrder thisClone = this.clone();
        MyOrder otherClone = other.clone();

        return Arrays.asList(thisClone, otherClone);

    }

    @Override
    protected MyOrder clone() {
        MyOrder clone = new MyOrder();
        if (CollectionUtil.isNotEmpty(clone.getOriOrders())) {
            clone.orders.clear();
        }
        clone.orders.addAll(this.orders);
        if (CollectionUtil.isNotEmpty(clone.getCovOrders())) {
            clone.covOrders.clear();
        }
        clone.covOrders.addAll(this.covOrders);
        if (CollectionUtil.isNotEmpty(clone.getOriOrders())) {
            clone.oriOrders.clear();
        }
        clone.oriOrders.addAll(this.oriOrders);
        clone.startTime = this.startTime;
        clone.endTime = this.endTime;
        return clone;
    }

    /**
     * 将轮播广告与定时广告交互播放次序
     *
     * @param orders
     * @param covers
     * @param oriOrders
     */
    private void checkCover(List<Order> orders, List<Order> covers, List<Order> oriOrders) {
        orders.sort((o1, o2) -> o1.getStartTime() - o2.getStartTime());
        int length = orders.size();

        int time = this.startTime;
        int index = 1;
        for (int i = 0; i < length - 1; i++) {
            boolean isCover = true;

            Order order = orders.get(i);

            for (int j = 0; j < covers.size(); j++) {
                Order cover = covers.get(j);
                if (cover.getStartTime() == time ) {
                    int m = orders.indexOf(cover);

//                    System.out.println(index++);
//                    System.out.println(time);
//                    System.out.println(order);
//                    System.out.println(cover);
//                    try {
//                        System.out.println(orders.get(m));
//                    } catch (Exception e) {
//                        int error = 1;
//                    }
//                    System.out.println("=======================");

                    orders.set(i, cover);
                    orders.set(m, order);
                    time += cover.getPlayTime();
                    isCover = false;
//                    break;
                }
//                if((time + order.getPlayTime() > cover.getStartTime()) && (time < cover.getStartTime()) && order.getPlayType() != RuleConstants.PlayType.COVER.getValue()){
//                    int m = orders.indexOf(cover);
//
//                    int cells = order.getPlayTime()/15;
////                    sout(orders);
//                    orders.remove(i);
//                    orders.add(i, cover);
//                    orders.remove(m);
//                    orders.add(i, new Order(true));
//                    for(int k = i;k<i+cells-1;k++){
//                        orders.add(k,new Order(true));
//                    }
//                    time += (cells-1)*15+ cover.getPlayTime() - order.getPlayTime();
//                    isCover=false;
////                    sout(orders);
//                }
            }

            if (isCover) {
                time += order.getPlayTime();
            }
            isCover = true;
        }
    }
}
